Add a GtkWindowGroup struct that allows grouping together multiple windows
authorOwen Taylor <otaylor@redhat.com>
Thu, 14 Jun 2001 21:44:01 +0000 (21:44 +0000)
committerOwen Taylor <otaylor@src.gnome.org>
Thu, 14 Jun 2001 21:44:01 +0000 (21:44 +0000)
Fri Jun  8 17:56:52 2001  Owen Taylor  <otaylor@redhat.com>

* gtk/gtkwindow.[ch] gtk/gtkmain.c: Add a GtkWindowGroup struct
that allows grouping together multiple windows so that grabs
within that set of windows only affect those windows.

* gtk/gtkmain.c gtk/gtkwidget.[ch]: Add a "grab_notify"
signal for notification when a widget becomes shadowed
by a grab or is no longer shadowed by a grab.

* gtk/gtkwidget.c (gtk_widget_propagate_state)
  gtk/gtkmain.c: (gtk_widget_grab_add): Don't allow
insenstive widgets to maintain a grab.

16 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gdk/gdkwindow.h
gtk/gtkmain.c
gtk/gtkplug.c
gtk/gtkplug.h
gtk/gtksocket.c
gtk/gtkwidget.c
gtk/gtkwidget.h
gtk/gtkwindow.c
gtk/gtkwindow.h

index 8508039a85cac312e778d5ac2282f4a6d1153dfc..b1691e51193c659f447391c0a44e262d0e9f6ebb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+Fri Jun  8 17:56:52 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtkwindow.[ch] gtk/gtkmain.c: Add a GtkWindowGroup struct
+       that allows grouping together multiple windows so that grabs
+       within that set of windows only affect those windows.
+
+       * gtk/gtkmain.c gtk/gtkwidget.[ch]: Add a "grab_notify"
+       signal for notification when a widget becomes shadowed
+       by a grab or is no longer shadowed by a grab.
+
+       * gtk/gtkwidget.c (gtk_widget_propagate_state)
+         gtk/gtkmain.c: (gtk_widget_grab_add): Don't allow
+       insenstive widgets to maintain a grab.
+
 2001-06-14  Alexander Larsson  <alexl@redhat.com>
 
         * docs/README.linux-fb:
index 8508039a85cac312e778d5ac2282f4a6d1153dfc..b1691e51193c659f447391c0a44e262d0e9f6ebb 100644 (file)
@@ -1,3 +1,17 @@
+Fri Jun  8 17:56:52 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtkwindow.[ch] gtk/gtkmain.c: Add a GtkWindowGroup struct
+       that allows grouping together multiple windows so that grabs
+       within that set of windows only affect those windows.
+
+       * gtk/gtkmain.c gtk/gtkwidget.[ch]: Add a "grab_notify"
+       signal for notification when a widget becomes shadowed
+       by a grab or is no longer shadowed by a grab.
+
+       * gtk/gtkwidget.c (gtk_widget_propagate_state)
+         gtk/gtkmain.c: (gtk_widget_grab_add): Don't allow
+       insenstive widgets to maintain a grab.
+
 2001-06-14  Alexander Larsson  <alexl@redhat.com>
 
         * docs/README.linux-fb:
index 8508039a85cac312e778d5ac2282f4a6d1153dfc..b1691e51193c659f447391c0a44e262d0e9f6ebb 100644 (file)
@@ -1,3 +1,17 @@
+Fri Jun  8 17:56:52 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtkwindow.[ch] gtk/gtkmain.c: Add a GtkWindowGroup struct
+       that allows grouping together multiple windows so that grabs
+       within that set of windows only affect those windows.
+
+       * gtk/gtkmain.c gtk/gtkwidget.[ch]: Add a "grab_notify"
+       signal for notification when a widget becomes shadowed
+       by a grab or is no longer shadowed by a grab.
+
+       * gtk/gtkwidget.c (gtk_widget_propagate_state)
+         gtk/gtkmain.c: (gtk_widget_grab_add): Don't allow
+       insenstive widgets to maintain a grab.
+
 2001-06-14  Alexander Larsson  <alexl@redhat.com>
 
         * docs/README.linux-fb:
index 8508039a85cac312e778d5ac2282f4a6d1153dfc..b1691e51193c659f447391c0a44e262d0e9f6ebb 100644 (file)
@@ -1,3 +1,17 @@
+Fri Jun  8 17:56:52 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtkwindow.[ch] gtk/gtkmain.c: Add a GtkWindowGroup struct
+       that allows grouping together multiple windows so that grabs
+       within that set of windows only affect those windows.
+
+       * gtk/gtkmain.c gtk/gtkwidget.[ch]: Add a "grab_notify"
+       signal for notification when a widget becomes shadowed
+       by a grab or is no longer shadowed by a grab.
+
+       * gtk/gtkwidget.c (gtk_widget_propagate_state)
+         gtk/gtkmain.c: (gtk_widget_grab_add): Don't allow
+       insenstive widgets to maintain a grab.
+
 2001-06-14  Alexander Larsson  <alexl@redhat.com>
 
         * docs/README.linux-fb:
index 8508039a85cac312e778d5ac2282f4a6d1153dfc..b1691e51193c659f447391c0a44e262d0e9f6ebb 100644 (file)
@@ -1,3 +1,17 @@
+Fri Jun  8 17:56:52 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtkwindow.[ch] gtk/gtkmain.c: Add a GtkWindowGroup struct
+       that allows grouping together multiple windows so that grabs
+       within that set of windows only affect those windows.
+
+       * gtk/gtkmain.c gtk/gtkwidget.[ch]: Add a "grab_notify"
+       signal for notification when a widget becomes shadowed
+       by a grab or is no longer shadowed by a grab.
+
+       * gtk/gtkwidget.c (gtk_widget_propagate_state)
+         gtk/gtkmain.c: (gtk_widget_grab_add): Don't allow
+       insenstive widgets to maintain a grab.
+
 2001-06-14  Alexander Larsson  <alexl@redhat.com>
 
         * docs/README.linux-fb:
index 8508039a85cac312e778d5ac2282f4a6d1153dfc..b1691e51193c659f447391c0a44e262d0e9f6ebb 100644 (file)
@@ -1,3 +1,17 @@
+Fri Jun  8 17:56:52 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtkwindow.[ch] gtk/gtkmain.c: Add a GtkWindowGroup struct
+       that allows grouping together multiple windows so that grabs
+       within that set of windows only affect those windows.
+
+       * gtk/gtkmain.c gtk/gtkwidget.[ch]: Add a "grab_notify"
+       signal for notification when a widget becomes shadowed
+       by a grab or is no longer shadowed by a grab.
+
+       * gtk/gtkwidget.c (gtk_widget_propagate_state)
+         gtk/gtkmain.c: (gtk_widget_grab_add): Don't allow
+       insenstive widgets to maintain a grab.
+
 2001-06-14  Alexander Larsson  <alexl@redhat.com>
 
         * docs/README.linux-fb:
index 8508039a85cac312e778d5ac2282f4a6d1153dfc..b1691e51193c659f447391c0a44e262d0e9f6ebb 100644 (file)
@@ -1,3 +1,17 @@
+Fri Jun  8 17:56:52 2001  Owen Taylor  <otaylor@redhat.com>
+
+       * gtk/gtkwindow.[ch] gtk/gtkmain.c: Add a GtkWindowGroup struct
+       that allows grouping together multiple windows so that grabs
+       within that set of windows only affect those windows.
+
+       * gtk/gtkmain.c gtk/gtkwidget.[ch]: Add a "grab_notify"
+       signal for notification when a widget becomes shadowed
+       by a grab or is no longer shadowed by a grab.
+
+       * gtk/gtkwidget.c (gtk_widget_propagate_state)
+         gtk/gtkmain.c: (gtk_widget_grab_add): Don't allow
+       insenstive widgets to maintain a grab.
+
 2001-06-14  Alexander Larsson  <alexl@redhat.com>
 
         * docs/README.linux-fb:
index 9a6d4c0155085c4ba189373eec8c732814346eac..90d63ebbdc97b29b4b71b49e645eb9b3514cb0cb 100644 (file)
@@ -248,8 +248,6 @@ struct _GdkWindowObject
 struct _GdkWindowObjectClass
 {
   GdkDrawableClass parent_class;
-
-
 };
 
 /* Windows
index 94b5e4b57ee29a1e430f8b755cbc8bc097949feb..2d45b4fc148050779f602884ada9534bd8cd1054 100644 (file)
@@ -110,6 +110,8 @@ static void  gtk_message             (gchar              *str);
 static void  gtk_print                  (gchar              *str);
 #endif
 
+static GtkWindowGroup *gtk_main_get_window_group (GtkWidget   *widget);
+
 const guint gtk_major_version = GTK_MAJOR_VERSION;
 const guint gtk_minor_version = GTK_MINOR_VERSION;
 const guint gtk_micro_version = GTK_MICRO_VERSION;
@@ -122,9 +124,6 @@ static GList *current_events = NULL;
 
 static GSList *main_loops = NULL;      /* stack of currently executing main loops */
 
-static GSList *grabs = NULL;              /* A stack of unique grabs. The grabbing
-                                           *  widget is the first one on the list.
-                                           */
 static GList *init_functions = NULL;      /* A list of init functions.
                                            */
 static GList *quit_functions = NULL;      /* A list of quit functions.
@@ -754,6 +753,7 @@ gtk_main_do_event (GdkEvent *event)
 {
   GtkWidget *event_widget;
   GtkWidget *grab_widget;
+  GtkWindowGroup *window_group;
   GdkEvent *next_event;
   GList *tmp_list;
 
@@ -818,12 +818,14 @@ gtk_main_do_event (GdkEvent *event)
    * gtk_current_event_get().
    */
   current_events = g_list_prepend (current_events, event);
+
+  window_group = gtk_main_get_window_group (event_widget);
   
   /* If there is a grab in effect...
    */
-  if (grabs)
+  if (window_group->grabs)
     {
-      grab_widget = grabs->data;
+      grab_widget = window_group->grabs->data;
       
       /* If the grab widget is an ancestor of the event widget
        *  then we send the event to the original event widget.
@@ -855,7 +857,7 @@ gtk_main_do_event (GdkEvent *event)
       
     case GDK_DELETE:
       gtk_widget_ref (event_widget);
-      if ((!grabs || gtk_widget_get_toplevel (grabs->data) == event_widget) &&
+      if ((!window_group->grabs || gtk_widget_get_toplevel (window_group->grabs->data) == event_widget) &&
          !gtk_widget_event (event_widget, event))
        gtk_widget_destroy (event_widget);
       gtk_widget_unref (event_widget);
@@ -974,39 +976,131 @@ gtk_false (void)
   return FALSE;
 }
 
+static GtkWindowGroup *
+gtk_main_get_window_group (GtkWidget   *widget)
+{
+  GtkWidget *toplevel = NULL;
+
+  if (widget)
+    toplevel = gtk_widget_get_toplevel (widget);
+
+  if (toplevel && GTK_IS_WINDOW (toplevel))
+    return _gtk_window_get_group (GTK_WINDOW (toplevel));
+  else
+    return _gtk_window_get_group (NULL);
+}
+
+typedef struct
+{
+  gboolean was_grabbed;
+  GtkWidget *grab_widget;
+} GrabNotifyInfo;
+
+static void
+gtk_grab_notify_foreach (GtkWidget *child,
+                        gpointer   data)
+                        
+{
+  GrabNotifyInfo *info = data;
+
+  if (child != info->grab_widget)
+    {
+      g_object_ref (G_OBJECT (child));
+
+      gtk_signal_emit_by_name (GTK_OBJECT (child), "grab_notify", info->was_grabbed);
+
+      if (GTK_IS_CONTAINER (child))
+       gtk_container_foreach (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
+      
+      g_object_unref (G_OBJECT (child));
+    }
+}
+
+static void
+gtk_grab_notify (GtkWindowGroup *group,
+                GtkWidget      *grab_widget,
+                gboolean        was_grabbed)
+{
+  GList *toplevels;
+  GrabNotifyInfo info;
+
+  info.grab_widget = grab_widget;
+  info.was_grabbed = was_grabbed;
+
+  g_object_ref (group);
+  g_object_ref (grab_widget);
+
+  toplevels = gtk_window_list_toplevels ();
+  g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
+                           
+  while (toplevels)
+    {
+      GtkWindow *toplevel = toplevels->data;
+      toplevels = g_list_delete_link (toplevels, toplevels);
+
+      if (group == toplevel->group)
+       gtk_container_foreach (GTK_CONTAINER (toplevel), gtk_grab_notify_foreach, &info);
+      g_object_unref (toplevel);
+    }
+
+  g_object_unref (group);
+  g_object_unref (grab_widget);
+}
+
 void
 gtk_grab_add (GtkWidget *widget)
 {
+  GtkWindowGroup *group;
+  gboolean was_grabbed;
+  
   g_return_if_fail (widget != NULL);
   
-  if (!GTK_WIDGET_HAS_GRAB (widget))
+  if (!GTK_WIDGET_HAS_GRAB (widget) && GTK_WIDGET_IS_SENSITIVE (widget))
     {
       GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_GRAB);
       
-      grabs = g_slist_prepend (grabs, widget);
+      group = gtk_main_get_window_group (widget);
+
+      was_grabbed = (group->grabs != NULL);
+      
       gtk_widget_ref (widget);
+      group->grabs = g_slist_prepend (group->grabs, widget);
+
+      if (!was_grabbed)
+       gtk_grab_notify (group, widget, FALSE);
     }
 }
 
 GtkWidget*
 gtk_grab_get_current (void)
 {
-  if (grabs)
-    return GTK_WIDGET (grabs->data);
+  GtkWindowGroup *group;
+
+  group = gtk_main_get_window_group (NULL);
+
+  if (group->grabs)
+    return GTK_WIDGET (group->grabs->data);
   return NULL;
 }
 
 void
 gtk_grab_remove (GtkWidget *widget)
 {
+  GtkWindowGroup *group;
+  
   g_return_if_fail (widget != NULL);
   
   if (GTK_WIDGET_HAS_GRAB (widget))
     {
       GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_GRAB);
+
+      group = gtk_main_get_window_group (widget);
+      group->grabs = g_slist_remove (group->grabs, widget);
       
-      grabs = g_slist_remove (grabs, widget);
       gtk_widget_unref (widget);
+
+      if (!group->grabs)
+       gtk_grab_notify (group, widget, TRUE);
     }
 }
 
index 1f7319b390c21e9a8dc8d0db05c16a24e6adc1da..fa2b37c9f2e61e6fbc23270fa50e0144fa3fc786 100644 (file)
@@ -119,10 +119,6 @@ gtk_plug_init (GtkPlug *plug)
 
   window->type = GTK_WINDOW_TOPLEVEL;
   window->auto_shrink = TRUE;
-
-#if 0  
-  gtk_window_set_grab_group (window, window);
-#endif  
 }
 
 void
@@ -168,10 +164,11 @@ gtk_plug_unrealize (GtkWidget *widget)
       plug->socket_window = NULL;
     }
 
-#if 0  
   if (plug->modality_window)
     handle_modality_off (plug);
-#endif  
+
+  gtk_window_group_remove_window (plug->modality_group, GTK_WINDOW (plug));
+  g_object_unref (plug->modality_group);
   
   if (GTK_WIDGET_CLASS (parent_class)->unrealize)
     (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
@@ -236,6 +233,9 @@ gtk_plug_realize (GtkWidget *widget)
   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
 
   gdk_window_add_filter (widget->window, gtk_plug_filter_func, widget);
+
+  plug->modality_group = gtk_window_group_new ();
+  gtk_window_group_add_window (plug->modality_group, window);
 }
 
 static gboolean
@@ -574,27 +574,22 @@ focus_first_last (GtkPlug          *plug,
 static void
 handle_modality_on (GtkPlug *plug)
 {
-#if 0
   if (!plug->modality_window)
     {
       plug->modality_window = gtk_window_new (GTK_WINDOW_POPUP);
-      gtk_window_set_grab_group (GTK_WINDOW (plug->modality_window), GTK_WINDOW (plug));
+      gtk_window_group_add_window (plug->modality_group, GTK_WINDOW (plug->modality_window));
       gtk_grab_add (plug->modality_window);
     }
-#endif  
 }
 
 static void
 handle_modality_off (GtkPlug *plug)
 {
-#if 0  
   if (plug->modality_window)
     {
-      gtk_grab_remove (plug->modality_window);
       gtk_widget_destroy (plug->modality_window);
       plug->modality_window = NULL;
     }
-#endif  
 }
 
 static void
index ce41c5a6a82b6229c42f85be403d95dc4117c569..37907574dab1dd193fdcef297e28dccf302db6fb 100644 (file)
@@ -53,6 +53,8 @@ struct _GtkPlug
   GtkWindow window;
 
   GdkWindow *socket_window;
+  GtkWidget *modality_window;
+  GtkWindowGroup *modality_group;
   gboolean   same_app;
 };
 
index 754ca0e0f9cd4c89a5a5fb47339f95f181a43adc..77d391b29440a38b87d24d0524b8170a730b5078 100644 (file)
@@ -119,9 +119,7 @@ gtk_socket_class_init (GtkSocketClass *class)
   widget_class->size_request = gtk_socket_size_request;
   widget_class->size_allocate = gtk_socket_size_allocate;
   widget_class->hierarchy_changed = gtk_socket_hierarchy_changed;
-#if 0  
   widget_class->grab_notify = gtk_socket_grab_notify;
-#endif  
   widget_class->key_press_event = gtk_socket_key_press_event;
   widget_class->focus_in_event = gtk_socket_focus_in_event;
   widget_class->focus_out_event = gtk_socket_focus_out_event;
index c6ba8adc1a462dd1300afe46badd689e80dfa943..880d9e3159beb167a91f1bc0daf57497be34daaf 100644 (file)
@@ -65,6 +65,7 @@ enum {
   HIERARCHY_CHANGED,
   STYLE_SET,
   DIRECTION_CHANGED,
+  GRAB_NOTIFY,
   ADD_ACCELERATOR,
   REMOVE_ACCELERATOR,
   ACTIVATE_MNEMONIC,
@@ -632,6 +633,14 @@ gtk_widget_class_init (GtkWidgetClass *klass)
                    gtk_marshal_VOID__ENUM,
                    GTK_TYPE_NONE, 1,
                    GTK_TYPE_TEXT_DIRECTION);
+  widget_signals[GRAB_NOTIFY] =
+    gtk_signal_new ("grab_notify",
+                   GTK_RUN_FIRST,
+                   GTK_CLASS_TYPE (object_class),
+                    GTK_SIGNAL_OFFSET (GtkWidgetClass, grab_notify),
+                   gtk_marshal_VOID__BOOLEAN,
+                   GTK_TYPE_NONE, 1,
+                   GTK_TYPE_BOOL);
   widget_signals[ADD_ACCELERATOR] =
     gtk_accel_group_create_add (GTK_CLASS_TYPE (object_class), GTK_RUN_LAST,
                                GTK_SIGNAL_OFFSET (GtkWidgetClass, add_accelerator));
@@ -5283,8 +5292,13 @@ gtk_widget_propagate_state (GtkWidget           *widget,
   if (old_state != GTK_WIDGET_STATE (widget))
     {
       gtk_widget_ref (widget);
+      
+      if (!GTK_WIDGET_IS_SENSITIVE (widget) && GTK_HAS_GRAB (widget))
+       gtk_grab_remove (widget);
+      
       gtk_signal_emit (GTK_OBJECT (widget), widget_signals[STATE_CHANGED], old_state);
       
+      
       if (GTK_IS_CONTAINER (widget))
        {
          data->parent_sensitive = (GTK_WIDGET_IS_SENSITIVE (widget) != FALSE);
index a1107e95580b7cf52306b820fc4e428af1324b58..396a8033d175b380f9bea178c85b5497d3c8b950 100644 (file)
@@ -258,6 +258,8 @@ struct _GtkWidgetClass
                                GtkStyle         *previous_style);
   void (* direction_changed)   (GtkWidget        *widget,
                                GtkTextDirection  previous_direction);
+  void (* grab_notify)         (GtkWidget        *widget,
+                               gboolean          was_grabbed);
   
   /* accelerators */
   void (* add_accelerator)     (GtkWidget      *widget,
index 0880b3a89fca0bf8de1610e5798780d6b7ddb686..197933d783d171bd1c9a435f16df6b75089bb762 100644 (file)
@@ -1599,6 +1599,9 @@ gtk_window_destroy (GtkObject *object)
       gtk_widget_unref (GTK_WIDGET (window));
     }
 
+  if (window->group)
+    gtk_window_group_remove_window (window->group, window);
+
   GTK_OBJECT_CLASS (parent_class)->destroy (object);
 }
 
@@ -3159,8 +3162,6 @@ gtk_window_set_frame_dimensions (GtkWindow *window,
     }
 }
 
-
-
 /**
  * gtk_window_present:
  * @window: a #GtkWindow
@@ -3607,3 +3608,145 @@ gtk_window_begin_move_drag  (GtkWindow *window,
                               root_x, root_y,
                               timestamp);
 }
+
+
+static void
+gtk_window_group_class_init (GtkWindowGroupClass *klass)
+{
+}
+
+GtkType
+gtk_window_group_get_type (void)
+{
+  static GtkType window_group_type = 0;
+
+  if (!window_group_type)
+    {
+      static const GTypeInfo window_group_info =
+      {
+       sizeof (GtkWindowGroupClass),
+       NULL,           /* base_init */
+       NULL,           /* base_finalize */
+       (GClassInitFunc) gtk_window_group_class_init,
+       NULL,           /* class_finalize */
+       NULL,           /* class_data */
+       sizeof (GtkWindowGroup),
+       16,             /* n_preallocs */
+       (GInstanceInitFunc) NULL,
+      };
+
+      window_group_type = g_type_register_static (G_TYPE_OBJECT, "GtkWindowGroup", &window_group_info, 0);
+    }
+
+  return window_group_type;
+}
+
+/**
+ * gtk_window_group_new:
+ * 
+ * Create a new #GtkWindowGroup object. Grabs added with
+ * gtk_window_grab_add() only affect windows within the
+ * same #GtkWindowGroup
+ * 
+ * Return value: 
+ **/
+GtkWindowGroup *
+gtk_window_group_new (void)
+{
+  return g_object_new (GTK_TYPE_WINDOW_GROUP, NULL);
+}
+
+static void
+window_group_cleanup_grabs (GtkWindowGroup *group,
+                           GtkWindow      *window)
+{
+  GSList *tmp_list;
+  GSList *to_remove = NULL;
+
+  tmp_list = window_group->grabs;
+  while (tmp_list)
+    {
+      if (gtk_widget_get_toplevel (tmp_list->data) == window)
+       to_remove = g_slist_prepend (to_remove, g_object_ref (tmp_list->data));
+      tmp_list = tmp_list->next;
+    }
+
+  while (to_remove)
+    {
+      gtk_grab_remove (to_remove->data);
+      g_object_unref (to_remove->data);
+      to_remove = g_slist_delete_link (to_remove, to_remove);
+    }
+}
+
+/**
+ * gtk_window_group_add_widget:
+ * @window_group: a #GtkWindowGroup
+ * @window: the #GtkWindow to add
+ * 
+ * Add a window to a #GtkWindowGroup. 
+ **/
+void
+gtk_window_group_add_window (GtkWindowGroup *window_group,
+                            GtkWindow      *window)
+{
+  g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
+  g_return_if_fail (GTK_IS_WINDOW (window));
+
+  if (window->group != window_group)
+    {
+      g_object_ref (window);
+      g_object_ref (window_group);
+      
+      if (window->group)
+       gtk_window_group_remove_window (window->group, window);
+      else
+       window_group_cleanup_grabs (_gtk_window_get_group (NULL), window);
+
+      window->group = window_group;
+
+      g_object_unref (window);
+    }
+}
+
+/**
+ * gtk_window_group_remove_window:
+ * @window_group: a #GtkWindowGroup
+ * @window: the #GtkWindow to remove
+ * 
+ * Removes a window from a #GtkWindowGroup.
+ **/
+void
+gtk_window_group_remove_window (GtkWindowGroup *window_group,
+                               GtkWindow      *window)
+{
+  g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group));
+  g_return_if_fail (GTK_IS_WIDGET (window));
+  g_return_if_fail (window->group == window_group);
+
+  g_object_ref (window);
+
+  window_group_cleanup_grabs (window_group, window);
+  window->group = NULL;
+  
+  g_object_unref (G_OBJECT (window_group));
+  g_object_unref (window);
+}
+
+/* Return the group for the window or the default group
+ */
+GtkWindowGroup *
+_gtk_window_get_group (GtkWindow *window)
+{
+  if (window && window->group)
+    return window->group;
+  else
+    {
+      static GtkWindowGroup *default_group = NULL;
+
+      if (!default_group)
+       default_group = gtk_window_group_new ();
+
+      return default_group;
+    }
+}
index 7cbc19a512c36f1863ce220af49a6b34030913c7..32c874a97983ae55653e3f50d6d3b15918038408 100644 (file)
@@ -50,6 +50,8 @@ extern "C" {
 typedef struct _GtkWindow             GtkWindow;
 typedef struct _GtkWindowClass        GtkWindowClass;
 typedef struct _GtkWindowGeometryInfo GtkWindowGeometryInfo;
+typedef struct _GtkWindowGroup        GtkWindowGroup;
+typedef struct _GtkWindowGroupClass   GtkWindowGroupClass;
 
 struct _GtkWindow
 {
@@ -65,6 +67,7 @@ struct _GtkWindow
   GtkWindow *transient_parent;
   GtkWindowGeometryInfo *geometry_info;
   GdkWindow *frame;
+  GtkWindowGroup *group;
 
   guint16 resize_count;
 
@@ -123,6 +126,24 @@ struct _GtkWindowClass
                                         GtkDirectionType direction);  
 };
 
+#define GTK_TYPE_WINDOW_GROUP             (gtk_window_group_get_type ())
+#define GTK_WINDOW_GROUP(object)          (G_TYPE_CHECK_INSTANCE_CAST ((object), GTK_TYPE_WINDOW_GROUP, GtkWindowGroup))
+#define GTK_WINDOW_GROUP_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_WINDOW_GROUP, GtkWindowGroupClass))
+#define GTK_IS_WINDOW_GROUP(object)       (G_TYPE_CHECK_INSTANCE_TYPE ((object), GTK_TYPE_WINDOW_GROUP))
+#define GTK_IS_WINDOW_GROUP_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WINDOW_GROUP))
+#define GTK_WINDOW_GET_CLASS(obj)         (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_WINDOW_GROUP, GtkWindowGroupClass))
+
+struct _GtkWindowGroup
+{
+  GObject parent_instance;
+
+  GSList *grabs;
+};
+
+struct _GtkWindowGroupClass
+{
+  GObjectClass parent_class;
+};
 
 GtkType    gtk_window_get_type                 (void) G_GNUC_CONST;
 GtkWidget* gtk_window_new                      (GtkWindowType        type);
@@ -175,9 +196,9 @@ void       gtk_window_set_decorated           (GtkWindow *window,
                                                gboolean   setting);
 
 /* If window is set modal, input will be grabbed when show and released when hide */
-void       gtk_window_set_modal                (GtkWindow           *window,
-                                                gboolean             modal);
-GList*    gtk_window_list_toplevels           (void);
+void       gtk_window_set_modal      (GtkWindow *window,
+                                     gboolean   modal);
+GList*     gtk_window_list_toplevels (void);
 
 void     gtk_window_add_mnemonic          (GtkWindow       *window,
                                           guint            keyval,
@@ -225,23 +246,34 @@ void       gtk_window_set_default_size         (GtkWindow           *window,
                                                gint                 width,
                                                gint                 height);
 
+/* Window groups
+ */
+GType            gtk_window_group_get_type      (void) G_GNUC_CONST;;
+
+GtkWindowGroup * gtk_window_group_new           (void);
+void             gtk_window_group_add_window    (GtkWindowGroup     *window_group,
+                                                GtkWindow          *window);
+void             gtk_window_group_remove_window (GtkWindowGroup     *window_group,
+                                                GtkWindow          *window);
+
 /* --- internal functions --- */
-void       gtk_window_set_focus                (GtkWindow           *window,
-                                               GtkWidget           *focus);
-void       gtk_window_set_default              (GtkWindow           *window,
-                                               GtkWidget           *defaultw);
-void       gtk_window_remove_embedded_xid      (GtkWindow           *window,
-                                               guint                xid);
-void       gtk_window_add_embedded_xid         (GtkWindow           *window,
-                                               guint                xid);
-void       _gtk_window_reposition              (GtkWindow           *window,
-                                               gint                 x,
-                                               gint                 y);
-void       _gtk_window_constrain_size          (GtkWindow           *window,
-                                               gint                 width,
-                                               gint                 height,
-                                               gint                *new_width,
-                                               gint                *new_height);
+void            gtk_window_set_focus           (GtkWindow *window,
+                                               GtkWidget *focus);
+void            gtk_window_set_default         (GtkWindow *window,
+                                               GtkWidget *defaultw);
+void            gtk_window_remove_embedded_xid (GtkWindow *window,
+                                               guint      xid);
+void            gtk_window_add_embedded_xid    (GtkWindow *window,
+                                               guint      xid);
+void            _gtk_window_reposition         (GtkWindow *window,
+                                               gint       x,
+                                               gint       y);
+void            _gtk_window_constrain_size     (GtkWindow *window,
+                                               gint       width,
+                                               gint       height,
+                                               gint      *new_width,
+                                               gint      *new_height);
+GtkWindowGroup *_gtk_window_get_group          (GtkWindow *window);
 
 #ifdef __cplusplus
 }